/**
 * 设备服务
 * 提供设备连接和通信的统一接口，支持蓝牙和WiFi双模切换
 */

const AppConfig = require('../config/app.config');
const logger = require('../utils/logger').logger;
const WifiService = require('./wifi-service').getInstance();
const { CONNECTION_STATUS, HEALTH_STATUS } = require('./wifi-service');

// 连接模式
const CONNECTION_MODE = {
  AUTO: 0,        // 自动选择最佳连接方式
  BLUETOOTH: 1,   // 强制使用蓝牙连接
  WIFI: 2         // 强制使用WiFi连接
};

// 设备连接状态
const DEVICE_CONNECTION_STATUS = {
  DISCONNECTED: 0,  // 未连接
  CONNECTING: 1,    // 连接中
  CONNECTED: 2,     // 已连接
  ERROR: 3          // 连接错误
};

/**
 * 设备服务类
 */
class DeviceService {
  constructor() {
    this.deviceMap = new Map();         // 设备ID到设备信息的映射
    this.connectionMode = CONNECTION_MODE.AUTO;  // 默认连接模式
    this.switchingDevices = new Set();  // 正在切换连接方式的设备集合
    this.offlineCheckInterval = null;   // 离线设备检查定时器
    this.batteryThreshold = 20;         // 电量阈值，低于此值时优先使用蓝牙以节省设备电量
    
    // 初始化离线设备检查
    this._startOfflineCheck();
    
    // 监听设备在线状态变化
    this._listenDeviceStatus();
  }

  /**
   * 开始离线设备检查
   * @private
   */
  _startOfflineCheck() {
    // 停止现有定时器
    if (this.offlineCheckInterval) {
      clearInterval(this.offlineCheckInterval);
    }
    
    // 每30秒检查一次离线设备
    this.offlineCheckInterval = setInterval(() => {
      this.deviceMap.forEach((device, deviceId) => {
        // 检查设备是否离线
        if (this.getDeviceStatus(deviceId) === DEVICE_CONNECTION_STATUS.DISCONNECTED) {
          // 尝试重新连接离线设备
          this._tryReconnectDevice(deviceId);
        }
      });
    }, 30000);
  }

  /**
   * 监听设备状态变化
   * @private
   */
  _listenDeviceStatus() {
    // TODO: 实现设备状态变化监听
  }

  /**
   * 尝试重新连接设备
   * @param {string} deviceId - 设备ID
   * @private
   */
  _tryReconnectDevice(deviceId) {
    const device = this.deviceMap.get(deviceId);
    if (!device) return;
    
    // 检查是否正在切换连接方式
    if (this.switchingDevices.has(deviceId)) return;
    
    // 根据连接模式选择重连方式
    switch (this.connectionMode) {
      case CONNECTION_MODE.AUTO:
        // 优先尝试用之前成功的连接方式
        if (device.lastSuccessfulMode === CONNECTION_MODE.BLUETOOTH) {
          this._connectViaBluetooth(deviceId);
        } else if (device.lastSuccessfulMode === CONNECTION_MODE.WIFI) {
          this._connectViaWifi(deviceId);
        } else {
          // 没有历史记录，优先尝试蓝牙连接
          this._connectViaBluetooth(deviceId);
        }
        break;
        
      case CONNECTION_MODE.BLUETOOTH:
        this._connectViaBluetooth(deviceId);
        break;
        
      case CONNECTION_MODE.WIFI:
        this._connectViaWifi(deviceId);
        break;
        
      default:
        logger.error(`未知的连接模式: ${this.connectionMode}`);
    }
  }

  /**
   * 通过WiFi连接设备
   * @param {string} deviceId - 设备ID
   * @private
   */
  _connectViaWifi(deviceId) {
    const device = this.deviceMap.get(deviceId);
    if (!device || !device.wifiInfo) return;
    
    // 更新设备状态
    device.status = DEVICE_CONNECTION_STATUS.CONNECTING;
    device.connectionMode = CONNECTION_MODE.WIFI;
    
    // 连接WiFi设备
    WifiService.connectToDevice(deviceId, {
      deviceInfo: device.deviceInfo,
      ssid: device.wifiInfo.ssid,
      bssid: device.wifiInfo.bssid,
      password: device.wifiInfo.password,
      autoReconnect: true,
      onSuccess: () => {
        logger.info(`设备[${deviceId}]WiFi连接成功`);
        
        // 更新设备状态
        device.status = DEVICE_CONNECTION_STATUS.CONNECTED;
        device.lastSuccessfulMode = CONNECTION_MODE.WIFI;
        
        // 触发设备连接成功回调
        if (device.onConnected) {
          device.onConnected({ mode: CONNECTION_MODE.WIFI });
        }
      },
      onFailed: (err) => {
        logger.error(`设备[${deviceId}]WiFi连接失败`, err);
        
        // 更新设备状态
        device.status = DEVICE_CONNECTION_STATUS.ERROR;
        
        // 在自动模式下尝试蓝牙连接
        if (this.connectionMode === CONNECTION_MODE.AUTO) {
          logger.info(`尝试通过蓝牙连接设备[${deviceId}]`);
          this._connectViaBluetooth(deviceId);
        } else {
          // 触发设备连接失败回调
          if (device.onFailed) {
            device.onFailed(err);
          }
        }
      },
      onDisconnected: () => {
        logger.warn(`设备[${deviceId}]WiFi连接断开`);
        
        // 更新设备状态
        device.status = DEVICE_CONNECTION_STATUS.DISCONNECTED;
        
        // 触发设备断开连接回调
        if (device.onDisconnected) {
          device.onDisconnected({ mode: CONNECTION_MODE.WIFI });
        }
        
        // 在自动模式下尝试蓝牙连接
        if (this.connectionMode === CONNECTION_MODE.AUTO) {
          logger.info(`尝试通过蓝牙重新连接设备[${deviceId}]`);
          this._connectViaBluetooth(deviceId);
        }
      },
      onHealthUpdate: (healthInfo) => {
        // 处理WiFi健康状态更新
        this._handleWifiHealthUpdate(deviceId, healthInfo);
      }
    });
  }

  /**
   * 处理WiFi健康状态更新
   * @param {string} deviceId - 设备ID
   * @param {Object} healthInfo - 健康信息
   * @private
   */
  _handleWifiHealthUpdate(deviceId, healthInfo) {
    const device = this.deviceMap.get(deviceId);
    if (!device) return;
    
    // 更新设备WiFi健康信息
    device.wifiHealth = healthInfo;
    
    // 在自动模式下，如果WiFi信号较弱，考虑切换到蓝牙
    if (this.connectionMode === CONNECTION_MODE.AUTO && 
        device.connectionMode === CONNECTION_MODE.WIFI &&
        healthInfo.healthStatus === HEALTH_STATUS.POOR) {
      
      // 检查是否已在切换过程中
      if (this.switchingDevices.has(deviceId)) return;
      
      // 尝试切换到蓝牙
      logger.info(`设备[${deviceId}]WiFi信号较弱，尝试切换到蓝牙连接`);
      this._switchConnectionMode(deviceId, CONNECTION_MODE.BLUETOOTH);
    }
  }

  /**
   * 切换设备连接模式
   * @param {string} deviceId - 设备ID
   * @param {number} targetMode - 目标连接模式
   * @private
   */
  _switchConnectionMode(deviceId, targetMode) {
    const device = this.deviceMap.get(deviceId);
    if (!device || device.connectionMode === targetMode) return;
    
    // 标记设备正在切换
    this.switchingDevices.add(deviceId);
    
    // 记录当前连接模式
    const currentMode = device.connectionMode;
    
    // 根据目标模式切换
    switch (targetMode) {
      case CONNECTION_MODE.BLUETOOTH:
        // 断开WiFi连接
        if (currentMode === CONNECTION_MODE.WIFI) {
          WifiService.disconnectFromDevice(deviceId, () => {
            // 连接蓝牙
            this._connectViaBluetooth(deviceId);
            
            // 完成切换
            this.switchingDevices.delete(deviceId);
          });
        } else {
          // 直接连接蓝牙
          this._connectViaBluetooth(deviceId);
          this.switchingDevices.delete(deviceId);
        }
        break;
        
      case CONNECTION_MODE.WIFI:
        // 断开蓝牙连接
        if (currentMode === CONNECTION_MODE.BLUETOOTH) {
          
        } else {
          // 直接连接WiFi
          this._connectViaWifi(deviceId);
          this.switchingDevices.delete(deviceId);
        }
        break;
        
      case CONNECTION_MODE.AUTO:
        // 自动模式，根据设备情况选择最佳连接方式
        this._selectBestConnectionMode(deviceId, (bestMode) => {
          if (bestMode === currentMode) {
            // 最佳模式就是当前模式，无需切换
            this.switchingDevices.delete(deviceId);
            return;
          }
          
          // 切换到最佳模式
          this._switchConnectionMode(deviceId, bestMode);
        });
        break;
        
      default:
        logger.error(`未知的连接模式: ${targetMode}`);
        this.switchingDevices.delete(deviceId);
    }
  }

  /**
   * 选择最佳连接模式
   * @param {string} deviceId - 设备ID
   * @param {Function} callback - 回调函数，参数为最佳连接模式
   * @private
   */
  _selectBestConnectionMode(deviceId, callback) {
    const device = this.deviceMap.get(deviceId);
    if (!device) {
      callback(CONNECTION_MODE.BLUETOOTH); // 默认使用蓝牙
      return;
    }
    
    // 考虑多种因素选择最佳连接模式
    
    // 1. 电池电量因素：如果电量低于阈值，优先使用蓝牙以节省设备电量
    if (device.batteryLevel && device.batteryLevel < this.batteryThreshold) {
      callback(CONNECTION_MODE.BLUETOOTH);
      return;
    }
    
    // 2. 稳定性因素：如果之前的连接模式稳定，继续使用
    if (device.lastSuccessfulMode && 
        device.connectionHistory && 
        device.connectionHistory.length > 0) {
      
      const lastMode = device.lastSuccessfulMode;
      const history = device.connectionHistory;
      
      // 计算成功率
      const totalAttempts = history.length;
      const successCount = history.filter(record => record.success).length;
      const successRate = successCount / totalAttempts;
      
      // 如果成功率高于80%，继续使用当前模式
      if (successRate > 0.8) {
        callback(lastMode);
        return;
      }
    }
    
    // 3. WiFi信号强度因素
    if (device.wifiHealth && device.wifiHealth.signalStrength > 75) {
      // WiFi信号强，优先使用WiFi
      callback(CONNECTION_MODE.WIFI);
      return;
    }
    
    // 4. 默认使用蓝牙（考虑到一般情况下蓝牙更稳定）
    callback(CONNECTION_MODE.BLUETOOTH);
  }

  /**
   * 注册设备
   * @param {string} deviceId - 设备ID
   * @param {Object} options - 设备选项
   * @param {Object} options.deviceInfo - 设备信息
   * @param {Object} options.wifiInfo - WiFi连接信息
   * @param {string} options.wifiInfo.ssid - WiFi SSID
   * @param {string} options.wifiInfo.bssid - WiFi BSSID
   * @param {string} options.wifiInfo.password - WiFi密码
   * @param {number} options.batteryLevel - 电池电量
   * @param {Function} options.onConnected - 连接成功回调
   * @param {Function} options.onFailed - 连接失败回调
   * @param {Function} options.onDisconnected - 断开连接回调
   */
  registerDevice(deviceId, options = {}) {
    // 提取选项
    const { 
      deviceInfo = {}, 
      wifiInfo, 
      batteryLevel, 
      onConnected, 
      onFailed, 
      onDisconnected 
    } = options;
    
    // 创建设备记录
    this.deviceMap.set(deviceId, {
      deviceInfo,
      wifiInfo,
      batteryLevel,
      status: DEVICE_CONNECTION_STATUS.DISCONNECTED,
      connectionMode: null,
      lastSuccessfulMode: null,
      connectionHistory: [],
      onConnected,
      onFailed,
      onDisconnected
    });
    
    logger.info(`注册设备[${deviceId}]成功`);
  }

  /**
   * 连接设备
   * @param {string} deviceId - 设备ID
   * @param {Object} options - 连接选项
   * @param {number} options.mode - 连接模式
   * @param {Function} options.onConnected - 连接成功回调
   * @param {Function} options.onFailed - 连接失败回调
   */
  connectDevice(deviceId, options = {}) {
    // 获取设备信息
    const device = this.deviceMap.get(deviceId);
    if (!device) {
      if (options.onFailed) {
        options.onFailed({ errMsg: '设备未注册' });
      }
      return;
    }
    
    // 提取选项
    const { 
      mode = this.connectionMode, 
      onConnected, 
      onFailed 
    } = options;
    
    // 更新回调
    if (onConnected) device.onConnected = onConnected;
    if (onFailed) device.onFailed = onFailed;
    
    // 根据模式连接设备
    switch (mode) {
      case CONNECTION_MODE.AUTO:
        this._selectBestConnectionMode(deviceId, (bestMode) => {
          if (bestMode === CONNECTION_MODE.BLUETOOTH) {
            this._connectViaBluetooth(deviceId);
          } else {
            this._connectViaWifi(deviceId);
          }
        });
        break;
        
      case CONNECTION_MODE.BLUETOOTH:
        this._connectViaBluetooth(deviceId);
        break;
        
      case CONNECTION_MODE.WIFI:
        this._connectViaWifi(deviceId);
        break;
        
      default:
        logger.error(`未知的连接模式: ${mode}`);
        if (onFailed) {
          onFailed({ errMsg: '未知的连接模式' });
        }
    }
  }

  /**
   * 断开设备连接
   * @param {string} deviceId - 设备ID
   * @param {Function} callback - 断开连接回调
   */
  disconnectDevice(deviceId, callback) {
    // 获取设备信息
    const device = this.deviceMap.get(deviceId);
    if (!device) {
      if (callback) {
        callback({ success: false, errMsg: '设备未注册' });
      }
      return;
    }
    
    // 根据当前连接模式断开连接
    switch (device.connectionMode) {
      case CONNECTION_MODE.BLUETOOTH:
       
        break;
        
      case CONNECTION_MODE.WIFI:
        WifiService.disconnectFromDevice(deviceId, (res) => {
          // 更新设备状态
          device.status = DEVICE_CONNECTION_STATUS.DISCONNECTED;
          
          // 回调
          if (callback) {
            callback(res);
          }
        });
        break;
        
      default:
        // 设备未连接
        if (callback) {
          callback({ success: true, errMsg: '设备未连接' });
        }
    }
  }

  /**
   * 发送WiFi命令
   * @param {string} deviceId - 设备ID
   * @param {Object} command - 命令对象
   * @param {Object} options - 选项
   * @param {Function} options.onSuccess - 成功回调
   * @param {Function} options.onFailed - 失败回调
   */
  sendWifiCommand(deviceId, command, options = {}) {
    // 检查设备状态
    const device = this.deviceMap.get(deviceId);
    if (!device) {
      if (options.onFailed) {
        options.onFailed({ errMsg: '设备未注册' });
      }
      return;
    }
    
    // 判断当前连接模式是否为WiFi
    if (device.connectionMode !== CONNECTION_MODE.WIFI) {
      if (this.connectionMode === CONNECTION_MODE.AUTO) {
        // 自动切换到WiFi
        this._switchConnectionMode(deviceId, CONNECTION_MODE.WIFI, () => {
          // 切换完成后发送命令
          this._sendWifiCommandInternal(deviceId, command, options);
        });
      } else {
        // 非自动模式下报错
        if (options.onFailed) {
          options.onFailed({ errMsg: '设备未通过WiFi连接' });
        }
      }
      return;
    }
    
    // 发送WiFi命令
    this._sendWifiCommandInternal(deviceId, command, options);
  }

  /**
   * 内部方法：发送WiFi命令
   * @param {string} deviceId - 设备ID
   * @param {Object} command - 命令对象
   * @param {Object} options - 选项
   * @private
   */
  _sendWifiCommandInternal(deviceId, command, options = {}) {
    // 发送命令
    WifiService.sendCommand(deviceId, command, {
      onSuccess: (res) => {
        logger.info(`向设备[${deviceId}]发送WiFi命令成功`);
        
        // 记录成功历史
        this._recordConnectionHistory(deviceId, true, CONNECTION_MODE.WIFI);
        
        if (options.onSuccess) {
          options.onSuccess(res);
        }
      },
      onFailed: (err) => {
        logger.error(`向设备[${deviceId}]发送WiFi命令失败`, err);
        
        // 记录失败历史
        this._recordConnectionHistory(deviceId, false, CONNECTION_MODE.WIFI);
        
        if (options.onFailed) {
          options.onFailed(err);
        }
      }
    });
  }

  /**
   * 记录连接历史
   * @param {string} deviceId - 设备ID
   * @param {boolean} success - 是否成功
   * @param {number} mode - 连接模式
   * @private
   */
  _recordConnectionHistory(deviceId, success, mode) {
    const device = this.deviceMap.get(deviceId);
    if (!device) return;
    
    // 初始化历史记录
    if (!device.connectionHistory) {
      device.connectionHistory = [];
    }
    
    // 添加记录
    device.connectionHistory.push({
      timestamp: Date.now(),
      success,
      mode
    });
    
    // 最多保留20条记录
    if (device.connectionHistory.length > 20) {
      device.connectionHistory.shift();
    }
  }

  /**
   * 获取设备状态
   * @param {string} deviceId - 设备ID
   * @returns {number} 设备状态
   */
  getDeviceStatus(deviceId) {
    const device = this.deviceMap.get(deviceId);
    return device ? device.status : DEVICE_CONNECTION_STATUS.DISCONNECTED;
  }

  /**
   * 获取设备连接模式
   * @param {string} deviceId - 设备ID
   * @returns {number} 连接模式
   */
  getDeviceConnectionMode(deviceId) {
    const device = this.deviceMap.get(deviceId);
    return device ? device.connectionMode : null;
  }

  /**
   * 设置全局连接模式
   * @param {number} mode - 连接模式
   */
  setConnectionMode(mode) {
    if (mode !== CONNECTION_MODE.AUTO && 
        mode !== CONNECTION_MODE.BLUETOOTH && 
        mode !== CONNECTION_MODE.WIFI) {
      logger.error(`无效的连接模式: ${mode}`);
      return;
    }
    
    this.connectionMode = mode;
    logger.info(`设置全局连接模式为: ${mode}`);
  }

  /**
   * 获取全局连接模式
   * @returns {number} 连接模式
   */
  getConnectionMode() {
    return this.connectionMode;
  }

  /**
   * 获取所有已注册设备
   * @returns {Array} 设备列表
   */
  getAllDevices() {
    const devices = [];
    
    this.deviceMap.forEach((device, deviceId) => {
      devices.push({
        deviceId,
        status: device.status,
        connectionMode: device.connectionMode,
        deviceInfo: device.deviceInfo
      });
    });
    
    return devices;
  }
  
  /**
   * 移除设备
   * @param {string} deviceId - 设备ID 
   */
  removeDevice(deviceId) {
    // 先断开连接
    this.disconnectDevice(deviceId, () => {
      // 移除设备记录
      this.deviceMap.delete(deviceId);
      logger.info(`设备[${deviceId}]已移除`);
    });
  }
}

// 导出设备服务单例
let instance = null;
module.exports = {
  getInstance: function() {
    if (!instance) {
      instance = new DeviceService();
    }
    return instance;
  },
  CONNECTION_MODE,
  DEVICE_CONNECTION_STATUS
}; 